Imports System.Drawing
Imports System.IO
Imports System.Threading
Imports System.Windows.Forms

Imports Vintasoft.Imaging
Imports Vintasoft.Imaging.Codecs
Imports Vintasoft.Imaging.Codecs.Tiff
Imports Vintasoft.Imaging.ImageProcessing
Imports Vintasoft.Imaging.VisualTools

Imports DemosCommonCode
Imports DemosCommonCode.Imaging
Imports DemosCommonCode.Imaging.Codecs
Imports DemosCommonCode.Imaging.Codecs.Dialogs

Public Partial Class MainForm
	Inherits Form

	#Region "Fields"

	' Template of the title of application.
	Private _titlePrefix As String = "VintaSoft Multipage TIFF Demo v" + ImagingGlobalSettings.ProductVersion

	' Tiff file object that manipulates TIFF file
	Friend _tiff As TiffFile
	' Index of current TIFF page
	Friend _currentPageIndex As Integer = 0

	' Determines that the Open File Dialog is opened.
	Private _isFileDialogOpened As Boolean = False

	#End Region



	#Region "Constructors"

    Public Sub New()
        ImagingGlobalSettings.RegisterImaging("Leo Systems Inc.", _
                    "BettyKuo@leosys.com", _
                    "SIC4DD6KqPD7H/WtJjuoSjPO+AcRg5OTBXFk7QuhEnivV+wotGEVNhfU+x0HxdmG0BiiuPhqv01tqnGyikeR3MM7p1xicDXzDkN38+d+MQw3zjsrSurV2A/u0a9niLA/LSgAbJCN7sFiSMptQ9QC8+ZA+IGTkBoJrsZZAb1Ntlq0")

        InitializeComponent()

        CreateEmptyTiffFile()

        AddHandler imageViewer1.CutKeyPressed, New System.Windows.Forms.KeyEventHandler(AddressOf imageViewer1_CutKeyPressed)
        AddHandler imageViewer1.InsertKeyPressed, New System.Windows.Forms.KeyEventHandler(AddressOf imageViewer1_InsertKeyPressed)
        AddHandler imageViewer1.DeleteKeyPressed, New System.Windows.Forms.KeyEventHandler(AddressOf imageViewer1_DeleteKeyPressed)

        imageViewer1.RenderingQuality = ImageRenderingQuality.High

        viewerToolstrip.ImageViewer = Me.imageViewer1

        UpdateFormTitle()

        'CodecsFileFilters.SetFilters(openAllImagesFileDialog)

        DemosTools.SetDemoImagesFolder(openTiffImagesFileDialog)
        DemosTools.SetDemoImagesFolder(openAllImagesFileDialog)
    End Sub

	#End Region



	#Region "Properties"

	' Enables a visual instruments for viewing/editing the TiffFile.
	Public Property EnableChanging() As Boolean
		Get
			Return openToolStripMenuItem.Enabled
		End Get
		Set
			DemosTools.SetMenuEnabledState(fileToolStripMenuItem, value)
			viewerToolstrip.Enabled = value
			groupBoxFileManipulation.Enabled = value
			progressBarPage.Visible = Not value
			labelProgressBarPage.Visible = Not value
		End Set
	End Property

	#End Region



	#Region "Methods"

	#Region "'File' menu"

	''' <summary>
	''' Creates a new TIFF file.
	''' </summary>
	''' <param name="sender"></param>
	''' <param name="e"></param>
    Private Sub newToolStripMenuItem_Click(ByVal sender As Object, ByVal e As EventArgs) Handles newToolStripMenuItem.Click
        If saveTiffFileDialog.ShowDialog() = DialogResult.OK Then
            CloseTiffFile()

            Dim createNewFileForm As New CreateNewFileForm()
            createNewFileForm.ShowDialog()

            _tiff = New TiffFile(saveTiffFileDialog.FileName, createNewFileForm.FileFormat, createNewFileForm.FileVersion)
            SubscribeTiffFileEvents()

            UpdateForm()
        End If
    End Sub

	''' <summary>
	''' Opens the TIFF file.
	''' </summary>
	''' <param name="sender"></param>
	''' <param name="e"></param>
    Private Sub openToolStripMenuItem_Click(ByVal sender As Object, ByVal e As EventArgs) Handles viewerToolstrip.OpenFile, openToolStripMenuItem.Click
        If _isFileDialogOpened Then
            Return
        End If

        _isFileDialogOpened = True

        If openTiffImagesFileDialog.ShowDialog() = System.Windows.Forms.DialogResult.OK Then
            ' close TIFF file
            CloseTiffFile()

            Try
                ' open new TIFF file
                _tiff = New TiffFile(openTiffImagesFileDialog.FileName, False)
                SubscribeTiffFileEvents()
                ' view the first page of TIFF file in the image viewer
                If _tiff.Pages.Count > 0 Then
                    _currentPageIndex = 0
                    SetPageAsync()
                End If
                UpdateForm()
            Catch ex As Exception
                DemosTools.ShowErrorMessage("File load error", ex)
            End Try
        End If

        _isFileDialogOpened = False
    End Sub

	''' <summary>
	''' Subscribe to TiffFile events.
	''' </summary>
	Private Sub SubscribeTiffFileEvents()
		If _tiff IsNot Nothing Then
			AddHandler _tiff.Pages.PageCollectionEncodingProgress, New EventHandler(Of ProgressEventArgs)(AddressOf Pages_PageCollectionEncodingProgress)
			AddHandler _tiff.Pages.PageEncodingProgress, New EventHandler(Of ProgressEventArgs)(AddressOf Pages_PageEncodingProgress)
		End If
	End Sub

	''' <summary>
	''' Unsubscribe from TiffFile events.
	''' </summary>
	Private Sub UnsubscribeTiffFileEvents()
		If _tiff IsNot Nothing Then
			RemoveHandler _tiff.Pages.PageCollectionEncodingProgress, New EventHandler(Of ProgressEventArgs)(AddressOf Pages_PageCollectionEncodingProgress)
			RemoveHandler _tiff.Pages.PageEncodingProgress, New EventHandler(Of ProgressEventArgs)(AddressOf Pages_PageEncodingProgress)
		End If
	End Sub

	''' <summary>
	''' Remove the current image from the image viewer.
	''' </summary>
	Private Sub RemoveImageFromImageViewer()
		Dim image As VintasoftImage = imageViewer1.Image
		imageViewer1.Image = Nothing
		If image IsNot Nothing Then
			image.Dispose()
		End If
	End Sub

	''' <summary>
	''' Saves changes in the current TIFF file.
	''' </summary>
	''' <param name="sender"></param>
	''' <param name="e"></param>
    Private Sub saveToolStripMenuItem_Click(ByVal sender As Object, ByVal e As EventArgs) Handles saveToolStripMenuItem.Click
        If Not IsTiffFileExist() Then
            Return
        End If

        _tiff.SaveChanges()
    End Sub

	''' <summary>
	''' Save the current TIFF file as new file.
	''' </summary>
	''' <param name="sender"></param>
	''' <param name="e"></param>
    Private Sub saveAsToolStripMenuItem_Click(ByVal sender As Object, ByVal e As EventArgs) Handles saveAsToolStripMenuItem.Click
        If Not IsTiffFileExist() Then
            Return
        End If

        If _tiff.Filename Is Nothing AndAlso _tiff.Pages.Count = 0 Then
            MessageBox.Show("New file without pages cannot be saved.", "Save", MessageBoxButtons.OK, MessageBoxIcon.[Error])
            Return
        End If

        If saveTiffFileDialog.ShowDialog() = DialogResult.OK Then
            Try
                _tiff.SaveChanges(saveTiffFileDialog.FileName)
            Catch ex As Exception
                DemosTools.ShowErrorMessage(ex)
                Return
            End Try
            UpdateFormTitle()
        End If
    End Sub

	''' <summary>
	''' Packs the current TIFF file.
	''' </summary>
	''' <param name="sender"></param>
	''' <param name="e"></param>
    Private Sub packToolStripMenuItem_Click(ByVal sender As Object, ByVal e As EventArgs) Handles packToolStripMenuItem.Click
        If Not IsTiffFileExist() Then
            Return
        End If
        If _tiff.Filename Is Nothing Then
            MessageBox.Show("File must be saved to disk before packing.", "Pack", MessageBoxButtons.OK, MessageBoxIcon.[Error])
            Return
        End If

        ' pack current file to a temporary file
        Dim tempFilename As String = Path.GetTempFileName()
        _tiff.Pack(tempFilename)
        ' save filename of the current file and close current file
        Dim sourceFilename As String = _tiff.Filename
        _tiff.Dispose()
        ' replace current file by temporary file
        File.Delete(sourceFilename)
        File.Move(tempFilename, sourceFilename)
        ' open current file
        _tiff = New TiffFile(sourceFilename)
        SubscribeTiffFileEvents()
    End Sub


	''' <summary>
	''' Closes the current TIFF file.
	''' </summary>
	''' <param name="sender"></param>
	''' <param name="e"></param>
    Private Sub closeToolStripMenuItem_Click(ByVal sender As Object, ByVal e As EventArgs) Handles closeToolStripMenuItem.Click
        CloseTiffFile()
    End Sub

	''' <summary>
	''' Closes the application.
	''' </summary>
	''' <param name="sender"></param>
	''' <param name="e"></param>
    Private Sub exitToolStripMenuItem_Click(ByVal sender As Object, ByVal e As EventArgs) Handles exitToolStripMenuItem.Click
        CloseTiffFile()
        Close()
    End Sub

	Private Function IsTiffFileExist() As Boolean
		If _tiff Is Nothing Then
			Return False
		End If

		Return True
	End Function

	''' <summary>
	''' Create an empty TIFF file.
	''' </summary>
	Private Sub CreateEmptyTiffFile()
		' open new TIFF file
		_tiff = New TiffFile()
		'
		SubscribeTiffFileEvents()
		'
		UpdateForm()
	End Sub

	''' <summary>
	''' Closes the current TIFF file.
	''' </summary>
	Private Sub CloseTiffFile()
		' remove the current image from the image viewer
		RemoveImageFromImageViewer()

		' close previously opened TIFF file
		If _tiff IsNot Nothing Then
			_tiff.Dispose()
			_tiff = Nothing
		End If

		SetPageInfo()

		UpdateForm()
	End Sub

	#End Region


	#Region "'View' menu"

	''' <summary>
	''' Enable/disable centering of the image in the image viewer.
	''' </summary>
	''' <param name="sender"></param>
	''' <param name="e"></param>
    Private Sub centerImageToolStripMenuItem_Click(ByVal sender As Object, ByVal e As EventArgs) Handles centerImageToolStripMenuItem.Click
        If centerImageToolStripMenuItem.Checked Then
            imageViewer1.FocusPointAnchor = AnchorStyles.None
            imageViewer1.IsFocusPointFixed = True
            imageViewer1.ScrollToCenter()
        Else
            imageViewer1.FocusPointAnchor = AnchorStyles.Left Or AnchorStyles.Top
            imageViewer1.IsFocusPointFixed = True
        End If
    End Sub

	''' <summary>
	''' Change settings of the image viewer.
	''' </summary>
	''' <param name="sender"></param>
	''' <param name="e"></param>
    Private Sub imageViewerSettingsToolStripMenuItem_Click(ByVal sender As Object, ByVal e As EventArgs) Handles imageViewerSettingsToolStripMenuItem.Click
        Dim viewerSettingsDialog As New ImageViewerSettingsForm(imageViewer1)
        viewerSettingsDialog.ShowDialog()
    End Sub

	#End Region


	#Region "'Page' menu"

	#Region "Page Navigation"

    Private Sub imageViewerToolstrip_PageIndexChanged(ByVal sender As Object, ByVal e As ImageViewerToolstrip.PageIndexChangedEventArgs) Handles viewerToolstrip.PageIndexChanged
        If _tiff IsNot Nothing AndAlso e.SelectedPageIndex >= 0 AndAlso e.SelectedPageIndex < _tiff.Pages.Count AndAlso e.SelectedPageIndex <> _currentPageIndex AndAlso EnableChanging Then
            _currentPageIndex = e.SelectedPageIndex
            SetPageAsync()
        End If
    End Sub

    Private Sub firstPageToolStripMenuItem_Click(ByVal sender As Object, ByVal e As EventArgs) Handles firstPageToolStripMenuItem.Click
        If _tiff IsNot Nothing AndAlso _currentPageIndex > 0 Then
            _currentPageIndex = 0
            SetPageAsync()
        End If
    End Sub

    Private Sub previousPageToolStripMenuItem_Click(ByVal sender As Object, ByVal e As EventArgs) Handles previousPageToolStripMenuItem.Click
        If _tiff IsNot Nothing AndAlso _tiff.Pages.Count > 0 Then
            If _currentPageIndex > 0 Then
                _currentPageIndex -= 1
                SetPageAsync()
            End If
        End If
    End Sub

    Private Sub nextPageToolStripMenuItem_Click(ByVal sender As Object, ByVal e As EventArgs) Handles nextPageToolStripMenuItem.Click
        If _tiff IsNot Nothing AndAlso _tiff.Pages.Count > 0 Then
            If _currentPageIndex < (_tiff.Pages.Count - 1) Then
                _currentPageIndex += 1
                SetPageAsync()
            End If
        End If
    End Sub

    Private Sub lastPageToolStripMenuItem_Click(ByVal sender As Object, ByVal e As EventArgs) Handles lastPageToolStripMenuItem.Click
        If _tiff IsNot Nothing AndAlso _tiff.Pages.Count > 0 Then
            Dim lastPageIndex As Integer = _tiff.Pages.Count - 1
            If _currentPageIndex <> lastPageIndex Then
                _currentPageIndex = lastPageIndex
                SetPageAsync()
            End If
        End If
    End Sub

	#End Region


    Private Sub addPagesToolStripMenuItem_Click(ByVal sender As Object, ByVal e As EventArgs) Handles addPagesToolStripMenuItem.Click
        AddPages()
    End Sub

    Private Sub insertPagesToolStripMenuItem_Click(ByVal sender As Object, ByVal e As EventArgs) Handles insertPagesToolStripMenuItem.Click
        InsertPages(_currentPageIndex)
    End Sub

    Private Sub insertPagesAfterToolStripMenuItem_Click(ByVal sender As Object, ByVal e As EventArgs) Handles insertPagesAfterToolStripMenuItem.Click
        If _tiff.Pages.Count = 0 Then
            InsertPages(0)
        Else
            Dim pagesWereInserted As Boolean = InsertPages(System.Threading.Interlocked.Increment(_currentPageIndex))
            If Not pagesWereInserted Then
                _currentPageIndex -= 1
            End If
        End If
    End Sub

	''' <summary>
	''' Adds pages to existing TIFF file.
	''' </summary>
	Private Sub AddPages()
		If Not IsTiffFileExist() Then
			Return
		End If

		If openAllImagesFileDialog.ShowDialog() = System.Windows.Forms.DialogResult.OK Then
			If SetTiffCompression() Then
				Dim imageCollection As New ImageCollection()

				Try
					For Each fileName As String In openAllImagesFileDialog.FileNames
						imageCollection.Add(fileName)
					Next
				Catch ex As Exception
					DemosTools.ShowErrorMessage(ex)
					Return
				End Try

				EnableChanging = False

				_tiff.Pages.Add(imageCollection)
				imageCollection.ClearAndDisposeItems()

				_currentPageIndex = _tiff.Pages.Count - 1

				SetPageAsync()
			End If
		End If
	End Sub

	''' <summary>
	''' Inserts pages into existing TIFF file.
	''' </summary>
	''' <param name="pageNumber"></param>
	''' <returns></returns>
	Private Function InsertPages(pageNumber As Integer) As Boolean
		If Not IsTiffFileExist() Then
			Return False
		End If

		If openAllImagesFileDialog.ShowDialog() <> System.Windows.Forms.DialogResult.OK Then
			Return False
		End If

		If Not SetTiffCompression() Then
			Return False
		End If

		Dim imageCollection As New ImageCollection()
		Try
			For Each fileName As String In openAllImagesFileDialog.FileNames
				imageCollection.Add(fileName)
			Next
		Catch ex As Exception
			MessageBox.Show(ex.Message)
			Return False
		End Try

		EnableChanging = False
		_tiff.Pages.Insert(pageNumber, imageCollection)
		SetPageAsync()

		Return True
	End Function

	''' <summary>
	''' Removes current TIFF page from TIFF file.
	''' </summary>
	''' <param name="sender"></param>
	''' <param name="e"></param>
    Private Sub removePageToolStripMenuItem_Click(ByVal sender As Object, ByVal e As EventArgs) Handles removePageToolStripMenuItem.Click
        If Not IsTiffPageExist() Then
            Return
        End If

        Try
            _tiff.Pages.RemoveAt(_currentPageIndex)
        Catch ex As TiffFileException
            MessageBox.Show(ex.Message)
            Return
        End Try

        If _currentPageIndex >= (_tiff.Pages.Count - 1) Then
            _currentPageIndex = _tiff.Pages.Count - 1
        End If

        If _currentPageIndex >= 0 Then
            SetPageAsync()
        Else
            RemoveImageFromImageViewer()
            SetPageInfo()
        End If

        InvokeUpdateForm()
    End Sub

	''' <summary>
	''' Saves the current TIF page as image file.
	''' </summary>
	''' <param name="sender"></param>
	''' <param name="e"></param>
    Private Sub savePageToolStripMenuItem_Click(ByVal sender As Object, ByVal e As EventArgs) Handles savePageToolStripMenuItem.Click
        If Not IsTiffPageExist() Then
            Return
        End If

        saveFileDialog1.FileName = ""
        If saveFileDialog1.ShowDialog() <> System.Windows.Forms.DialogResult.OK Then
            Return
        End If

        Cursor = Cursors.WaitCursor
        Dim encoder As EncoderBase = AvailableEncoders.CreateEncoder(saveFileDialog1.FileName)
        If encoder.[GetType]() Is GetType(TiffEncoder) Then
            DirectCast(encoder, TiffEncoder).CreateNewFile = True
            DirectCast(encoder, TiffEncoder).Settings.Compression = TiffCompression.Auto
        End If
        Try
            _tiff.Pages(_currentPageIndex).Save(saveFileDialog1.FileName, encoder)
            MessageBox.Show(String.Format("Page {0} saved successfully.", _currentPageIndex + 1))
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try
        Cursor = Cursors.[Default]
    End Sub

	''' <summary>
	''' Shows the information about tags of current TIFF page.
	''' </summary>
	''' <param name="sender"></param>
	''' <param name="e"></param>
    Private Sub tagsInfoToolStripMenuItem_Click(ByVal sender As Object, ByVal e As EventArgs) Handles tagsInfoToolStripMenuItem.Click
        If Not IsTiffPageExist() Then
            Return
        End If

        Dim tiffPage As TiffPage = _tiff.Pages(_currentPageIndex)
        Using tagsInfoDlg As New TagInfoForm(tiffPage)
            tagsInfoDlg.ShowDialog()
        End Using
    End Sub


	#Region "Compression"

	Private Function SetTiffCompression() As Boolean
		Dim tiffEncoderSettingsForm As New TiffEncoderSettingsForm()
		tiffEncoderSettingsForm.AppendExistingDocumentEnabled = False
		tiffEncoderSettingsForm.EncoderSettings = _tiff.Pages.EncoderSettings
		Return tiffEncoderSettingsForm.ShowDialog() = DialogResult.OK
	End Function

	#End Region


	Private Function IsTiffPageExist() As Boolean
		If _tiff Is Nothing Then
			Return False
		End If
		If _tiff.Pages.Count = 0 Then
			Return False
		End If
		If _currentPageIndex < 0 Then
			Return False
		End If

		Return True
	End Function

	#End Region


	#Region "'Help' menu"

    Private Sub aboutToolStripMenuItem_Click(ByVal sender As Object, ByVal e As EventArgs) Handles aboutToolStripMenuItem.Click
        Dim dlg As New AboutBoxForm()
        dlg.ShowDialog()
    End Sub

	#End Region


	#Region "Page Info"

	Private Sub SetPageInfo()
		If _tiff IsNot Nothing Then
			viewerToolstrip.PageCount = _tiff.Pages.Count

			If _currentPageIndex >= 0 AndAlso _currentPageIndex < _tiff.Pages.Count Then
				Dim currentPage As TiffPage = _tiff.Pages(_currentPageIndex)

				labelPageInfo.Text = String.Format("Image {0} of {1}", _currentPageIndex + 1, _tiff.Pages.Count)

				Dim sPixelFormat As String = String.Format("Color({0})", currentPage.BitsPerPixel)
				If currentPage.BitsPerPixel = 1 Then
					sPixelFormat = "BW"
				ElseIf currentPage.BitsPerPixel > 1 AndAlso currentPage.BitsPerPixel <= 8 Then
					sPixelFormat = "Palette"
				End If

				labelImageInfo.Text = String.Format("Width={0}; Height={1}; Resolution={2}; PixelFormat={3}; Compression={4}", currentPage.Width, currentPage.Height, currentPage.Resolution, sPixelFormat, currentPage.Compression)

				Return
			End If
		End If
		labelPageInfo.Text = "No images"
		labelImageInfo.Text = ""
	End Sub

	Private Sub SetPageAsync()
		Cursor = Cursors.WaitCursor
		labelProgressBarPage.Text = "Loading image: "
		EnableChanging = False
		SetPageInfo()
		viewerToolstrip.SelectedPageIndex = _currentPageIndex

		Dim thread As New Thread(New ThreadStart(AddressOf SetPage))
		thread.IsBackground = True
		thread.Start()
	End Sub

	''' <summary>
	''' Loads a current page image from TIFF file.
	''' </summary>
	Private Sub SetPage()
		Dim async As Boolean = Me.InvokeRequired

		Dim image As VintasoftImage = Nothing
		Dim page As TiffPage = _tiff.Pages(_currentPageIndex)
		Try
			If async Then
				image = page.GetImage(AddressOf TiffPage_LoadingProgress)
			Else
				image = page.GetImage()
			End If
		Catch ex As TiffFileException
			MessageBox.Show(ex.Message)
		End Try

		If async Then
			Invoke(New SetImageViewerImageDelegate(AddressOf SetImageViewerImage), image)
		Else
			SetImageViewerImage(image)
		End If
	End Sub

	Private Sub SetImageViewerImage(image As VintasoftImage)
		If image IsNot Nothing Then
			Dim lastImage As VintasoftImage = imageViewer1.Image
			imageViewer1.Image = image
			If lastImage IsNot Nothing Then
				lastImage.Dispose()
			End If
		End If
		Cursor = Cursors.[Default]
		EnableChanging = True
		labelProgressBarPage.Text = "Encoding page: "
		InvokeUpdateForm()
	End Sub

	#End Region


	#Region "Form state"

	''' <summary>
	''' Update form safely.
	''' </summary>
	Private Sub InvokeUpdateForm()
		If InvokeRequired Then
			Invoke(New UpdateFormDelegate(AddressOf UpdateForm))
		Else
			UpdateForm()
		End If
	End Sub

	''' <summary>
	''' Update form not safely.
	''' </summary>
	Private Sub UpdateForm()
		UpdateFormTitle()
		If _tiff IsNot Nothing Then
			If Not groupBoxFileManipulation.Enabled Then
				groupBoxFileManipulation.Enabled = True
			End If

			Dim imagesCount As Integer = _tiff.Pages.Count

			comboBoxPageNumbers.Items.Clear()
			comboBoxPageFrom.Items.Clear()
			comboBoxPageTo.Items.Clear()
			For i As Integer = 1 To imagesCount
				comboBoxPageNumbers.Items.Add(i)
				comboBoxPageFrom.Items.Add(i)
				comboBoxPageTo.Items.Add(i)
			Next
			comboBoxPageNumbers.Items.Add(imagesCount + 1)
			comboBoxPageNumbers.SelectedIndex = 0
			If imagesCount > 0 Then
				removePageToolStripMenuItem.Enabled = True
				buttonRemovePages.Enabled = True
				comboBoxPageFrom.Enabled = True
				comboBoxPageTo.Enabled = True
				comboBoxPageTo.Enabled = True
				comboBoxPageFrom.SelectedIndex = 0
				comboBoxPageTo.SelectedIndex = 0
			Else
				removePageToolStripMenuItem.Enabled = False
				buttonRemovePages.Enabled = False
				comboBoxPageFrom.Enabled = InlineAssignHelper(comboBoxPageTo.Enabled, False)
				comboBoxPageTo.Enabled = False
			End If
		Else
			groupBoxFileManipulation.Enabled = False
			viewerToolstrip.PageCount = 0
		End If
	End Sub

	''' <summary>
	''' Updates progress safely.
	''' </summary>
	''' <param name="value"></param>
	''' <param name="progressBar"></param>
	Private Sub InvokeUpdateProgress(value As Integer, progressBar As ToolStripProgressBar)
		If InvokeRequired Then
			Invoke(New UpdateProgressDelegate(AddressOf UpdateProgress), value, progressBar)
		Else
			UpdateProgress(value, progressBar)
		End If
	End Sub

	''' <summary>
	''' Updates progress not safely.
	''' </summary>
	''' <param name="value"></param>
	''' <param name="progressBar"></param>
	Private Sub UpdateProgress(value As Integer, progressBar As ToolStripProgressBar)
		If progressBar Is progressBarPage Then
			progressBar.Visible = True
		Else
			progressBar.Visible = value <> 100
			labelProgressBarPageCollection.Visible = progressBar.Visible
		End If
		progressBar.Value = value
		Application.DoEvents()
	End Sub

	Private Sub UpdateFormTitle()
		If Not IsTiffFileExist() Then
			Text = _titlePrefix
		Else
			Dim filename As String = _tiff.Filename
			If filename Is Nothing Then
				filename = "(Untitled)"
			End If
			Text = String.Format("{0} - {1}", _titlePrefix, filename)
		End If
	End Sub

	#End Region


	#Region "Event Handlers"

	Private Sub Pages_PageCollectionEncodingProgress(sender As Object, e As ProgressEventArgs)
		InvokeUpdateProgress(e.Progress, progressBarPageCollection)
	End Sub

	Private Sub Pages_PageEncodingProgress(sender As Object, e As ProgressEventArgs)
		InvokeUpdateProgress(e.Progress, progressBarPage)
	End Sub

	Private Sub TiffPage_LoadingProgress(sender As Object, e As ProgressEventArgs)
		InvokeUpdateProgress(e.Progress, progressBarPage)
	End Sub

    Private Sub comboBoxPageFrom_SelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs) Handles comboBoxPageFrom.SelectedIndexChanged
        If comboBoxPageTo.SelectedIndex < comboBoxPageFrom.SelectedIndex Then
            comboBoxPageTo.SelectedIndex = comboBoxPageFrom.SelectedIndex
        End If
    End Sub

    Private Sub comboBoxPageTo_SelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs) Handles comboBoxPageTo.SelectedIndexChanged
        If comboBoxPageTo.SelectedIndex < comboBoxPageFrom.SelectedIndex Then
            comboBoxPageFrom.SelectedIndex = comboBoxPageTo.SelectedIndex
        End If
    End Sub


	#Region "Add_Pages, Insert_Pages and Remove_Pages handlers."

    Private Sub buttonAddPages_Click(ByVal sender As Object, ByVal e As EventArgs) Handles buttonAddPages.Click
        AddPages()
    End Sub

    Private Sub buttonInsertPages_Click(ByVal sender As Object, ByVal e As EventArgs) Handles buttonInsertPages.Click
        Dim pageNumber As Integer = CInt(comboBoxPageNumbers.SelectedItem) - 1
        InsertPages(pageNumber)
    End Sub

    Private Sub buttonRemovePages_Click(ByVal sender As Object, ByVal e As EventArgs) Handles buttonRemovePages.Click
        If _tiff IsNot Nothing Then
            Dim pageFrom As Integer = CInt(comboBoxPageFrom.SelectedItem) - 1
            Dim pageTo As Integer = CInt(comboBoxPageTo.SelectedItem) - 1
            Dim pagesCount As Integer = pageTo - pageFrom + 1

            Try
                _tiff.Pages.RemoveAt(pageFrom, pagesCount)
            Catch ex As TiffFileException
                MessageBox.Show(ex.Message)
                Return
            End Try
            If _currentPageIndex >= (_tiff.Pages.Count - 1) Then
                _currentPageIndex = _tiff.Pages.Count - 1
            End If
            If _currentPageIndex >= 0 Then
                SetPageAsync()
            Else
                RemoveImageFromImageViewer()
                SetPageInfo()
            End If

            InvokeUpdateForm()
        End If
    End Sub

	#End Region


	Private Sub imageViewer1_CutKeyPressed(sender As Object, e As KeyEventArgs)
		If _tiff IsNot Nothing Then
			Clipboard.SetImage(_tiff.Pages(_currentPageIndex).GetImage().GetAsBitmap())
			removePageToolStripMenuItem_Click(sender, e)
		End If
	End Sub

	Private Sub imageViewer1_InsertKeyPressed(sender As Object, e As KeyEventArgs)
		If _tiff IsNot Nothing Then
			' if clipboard contains the image
			If Clipboard.ContainsImage() Then
				Dim imageFromClipboard As Image
				Dim focusedImage As VintasoftImage
				Dim dlg As New InsertActionForm()
				If dlg.ShowDialog() = System.Windows.Forms.DialogResult.OK Then
					Select Case dlg.Action
						' add image as a new page of TIFF file after current image
						Case 1
							imageFromClipboard = Clipboard.GetImage()
							_currentPageIndex += 1
							EnableChanging = False
							_tiff.Pages.Insert(_currentPageIndex, New VintasoftImage(imageFromClipboard, True))
							SetPageAsync()
							Exit Select

						' overlay image from clipboard with current page of TIFF file
						Case 2
							imageFromClipboard = Clipboard.GetImage()
							' if there is focused image in the image viewer
							If imageViewer1.FocusedIndex <> -1 Then
								focusedImage = imageViewer1.Image
								' if size of image in clipboard is more than size of focused image
								If imageFromClipboard.Width >= focusedImage.Width AndAlso imageFromClipboard.Height >= focusedImage.Height Then
									_tiff.Pages.RemoveAt(_currentPageIndex)
									_tiff.Pages.Insert(_currentPageIndex, New VintasoftImage(imageFromClipboard, True))
								Else
									' if size of image in clipboard is less than size of focused image
									Dim copyToSelecton As Boolean = False
									If TypeOf imageViewer1.VisualTool Is RectangularSelectionToolWithCopyPaste Then
										If TryCast(imageViewer1.VisualTool, RectangularSelectionToolWithCopyPaste).Rectangle.Width > 0 AndAlso TryCast(imageViewer1.VisualTool, RectangularSelectionToolWithCopyPaste).Rectangle.Height > 0 Then
											copyToSelecton = True
										End If
									End If
									' copy image from clipboard to selection in focused image
									' if selection is made
									If copyToSelecton Then
										TryCast(imageViewer1.VisualTool, RectangularSelectionToolWithCopyPaste).PasteFromClipboard()
									Else
										' copy image from clipboard to specified place of focused image
										Dim dlg2 As New PasteImageForm(focusedImage.Width, focusedImage.Height)
										If dlg2.ShowDialog() = System.Windows.Forms.DialogResult.OK Then
											Dim overlayCommand As New OverlayCommand(New VintasoftImage(imageFromClipboard, True), New Point(dlg2.X, dlg2.Y))
											overlayCommand.ExecuteInPlace(focusedImage)
										End If
									End If

									EnableChanging = False
									Using overlayedImage As VintasoftImage = DirectCast(focusedImage.Clone(), VintasoftImage)
										_tiff.Pages.RemoveAt(_currentPageIndex)
										_tiff.Pages.Insert(_currentPageIndex, overlayedImage)
									End Using
								End If
							Else
								_currentPageIndex += 1
								EnableChanging = False
								_tiff.Pages.Insert(_currentPageIndex, New VintasoftImage(imageFromClipboard, True))
							End If
							SetPageAsync()
							Exit Select

						' replace focused image with the image from clipboard
						Case 3
							imageFromClipboard = Clipboard.GetImage()
							' if there is focused image in the image viewer
							EnableChanging = False
							If imageViewer1.FocusedIndex <> -1 Then
								_tiff.Pages.RemoveAt(_currentPageIndex)
								_tiff.Pages.Insert(_currentPageIndex, New VintasoftImage(imageFromClipboard, True))
							Else
								_currentPageIndex += 1
								_tiff.Pages.Insert(_currentPageIndex, New VintasoftImage(imageFromClipboard, True))
							End If
							SetPageAsync()
							Exit Select
					End Select
				End If
			End If
		End If
	End Sub

	Private Sub imageViewer1_DeleteKeyPressed(sender As Object, e As KeyEventArgs)
		removePageToolStripMenuItem_Click(sender, e)
	End Sub

    Private Sub MainForm_FormClosing(ByVal sender As Object, ByVal e As FormClosingEventArgs) Handles MyBase.FormClosing
        UnsubscribeTiffFileEvents()
    End Sub

	#End Region

	#End Region



	#Region "Delegates"

	Private Delegate Sub UpdateFormDelegate()

	Private Delegate Sub SetImageViewerImageDelegate(image As VintasoftImage)

	Private Delegate Sub UpdateProgressDelegate(value As Integer, progressBar As ToolStripProgressBar)
	Private Shared Function InlineAssignHelper(Of T)(ByRef target As T, value As T) As T
		target = value
		Return value
	End Function

	#End Region

End Class
